#include "InlineStream.h"
#include <time.h>
#include <cmath>
#include <iostream>
using namespace std;

int main(int argc, char** argv) {
	// Define peak to use to create simulated data stream
	unsigned int const sourceRefSize = 48;
	double* const sourceRef = new double[sourceRefSize] { -0.000966429, -0.00119964, -0.00118616, -0.000678582,
			0.00229951, 0.0217842, 0.0613074, 0.156733, 0.305301, 0.49182, 0.68358, 0.845512, 0.950986, 0.984521,
			0.944636, 0.842791, 0.687357, 0.527077, 0.380956, 0.260087, 0.168696, 0.105998, 0.0685462, 0.0484331,
			0.0353872, 0.0332753, 0.0334183, 0.0331892, 0.0318952, 0.0299273, 0.0283969, 0.0277491, 0.0273934,
			0.0265412, 0.0250565, 0.0232322, 0.0213166, 0.0190748, 0.0159684, 0.0131479, 0.0104398, 0.00725754,
			0.00329131, 0.00210918, 0.00147583, 0.000903992, 0.000475297, 0.000122942 };

	unsigned int const numSamples = 100000000;
	unsigned int const numPeaks = 10000;
	unsigned long const seed = 974487322007;
	/*
	 * InlineStream defined elsewhere.  Purpose is to randomly size and place
	 * sourceRef with statistical fluctuation.  Uses cubic interpolation to
	 * fine tune placement.
	 */
	InlineStream IS(numSamples, numPeaks, seed, sourceRef, sourceRefSize);

	/* Define reference peak to compare to stream.  This is just a smaller
	 * section of sourceRef.
	 */
	unsigned int const referenceSize = 21;
	double* const ref = new double[referenceSize] { 0.0217842, 0.0613074, 0.156733, 0.305301, 0.49182, 0.68358,
			0.845512, 0.950986, 0.984521, 0.944636, 0.842791, 0.687357, 0.527077, 0.380956, 0.260087, 0.168696,
			0.105998, 0.0685462, 0.0484331, 0.0353872, 0.0332753 };

	double refSum = 0;
	double factor;
	double ref2Sum = 0;
	double dataSum = 0;
	double data2Sum = 0;
	double dataRefSum;
	double result;

	// Normalize reference and prepare sums
	for (int i = 0; i < referenceSize; i++) {
		refSum += ref[i];
	}
	factor = 1.0 / refSum;
	for (int i = 0; i < referenceSize; i++) {
		ref[i] *= factor;
		ref2Sum += ref[i] * ref[i];
		dataSum += (IS.stream)[i];
		data2Sum += (IS.stream)[i] * (IS.stream)[i];
	}

	// (Number of Samples) Minus (Reference Size)
	unsigned int const NSMRS = numSamples - referenceSize;
	// (Reference Size) Times (Reference[i]^2(Sum on i))  Minus One
	double const RSTR2SMO = referenceSize * ref2Sum - 1;

	long startClock = clock();
	for (int i = 0; i < NSMRS; i++) {
		int* const tempStream = &(IS.stream)[i];

		// (Data[i]*Reference[i](Sum on i)) Times (Reference Size) Minus (Data Sum)
		double DRSTRSMDS = (tempStream[0] * ref[0] + tempStream[1] * ref[1] + tempStream[2] * ref[2] + tempStream[3]
				* ref[3] + tempStream[4] * ref[4] + tempStream[5] * ref[5] + tempStream[6] * ref[6] + tempStream[7]
				* ref[7] + tempStream[8] * ref[8] + tempStream[9] * ref[9] + tempStream[10] * ref[10] + tempStream[11]
				* ref[11] + tempStream[12] * ref[12] + tempStream[13] * ref[13] + tempStream[14] * ref[14]
				+ tempStream[15] * ref[15] + tempStream[16] * ref[16] + tempStream[17] * ref[17] + tempStream[18]
				* ref[18] + tempStream[19] * ref[19] + tempStream[20] * ref[20]) * referenceSize - dataSum;

		result = DRSTRSMDS * DRSTRSMDS / ((referenceSize * data2Sum - dataSum * dataSum) * RSTR2SMO);

		//// Use result

		dataSum += tempStream[referenceSize] - tempStream[0];
		data2Sum += tempStream[referenceSize] * tempStream[referenceSize] - tempStream[0] * tempStream[0];
	}
	double elapsedTime = ((double) (clock() - startClock)) / ((double) CLOCKS_PER_SEC);
	cout << fixed << "Elapsed time = " << elapsedTime << "\tTime ticks per second = " << CLOCKS_PER_SEC << "\n";

	return 0;
}
